package name.panitz.ludens.animationGame;

import javax.swing.*;
import java.awt.event.*;
import static java.awt.event.KeyEvent.*;
import java.util.*;

public class TrainFrogger extends AnimationPanel {

	private static final long serialVersionUID = 1L;
	final static int TRACK_HEIGHT = 75;
	final static int TRACK_NUMBER = 5;

	double maxSpeed = 5.5;
	double minSpeed = 0.5;

	int minSpace = 80;
	int maxSpace = 80;

	int resets = 0;
	int points = 0;
	String status = "";
	boolean bonusStageActive = false;
	long bonusPoints = 1500;
	long startTime = 0;
	long currentTime = 0;

	int n = 0;

	private MenuFrogger menu;

	GameObject frog;

	ImageIcon loadIcon(String fileName) {
		return new ImageIcon(getClass().getClassLoader().getResource(fileName));
	}

	ImageIcon[] trainIcons = { loadIcon("e120.png"), loadIcon("e140.png"),
			loadIcon("e103.png"), loadIcon("e182.png"), loadIcon("e110.png") };

	TrainFrogger() {
		super();
		this.setBackground(java.awt.Color.DARK_GRAY);
		preferredWidth = 800;
		preferredHeight = (TRACK_NUMBER + 2) * TRACK_HEIGHT;
		frog = new MovableImage("frog.png", preferredWidth / 2, preferredHeight
				- TRACK_HEIGHT);
		gos.add(frog);

		startTime();
		addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				switch (e.getKeyCode()) {
				case VK_LEFT:
					frog.getDeltaPos().addMod(new Vertex(-1, 0));
					break;
				case VK_RIGHT:
					frog.getDeltaPos().addMod(new Vertex(1, 0));
					break;
				case VK_UP:
					if (!(frog.getPos().getY() == 0)) {
						frog.getPos().addMod(new Vertex(0, -TRACK_HEIGHT));
						if (!bonusStageActive) {
							calculatePoints(10);
						} else {
							calculatePoints(-20);
						}
					}
					break;
				case VK_DOWN:
					if (!(frog.getPos().getY() == 450)) {
						frog.getPos().addMod(new Vertex(0, TRACK_HEIGHT));
						if (!bonusStageActive) {
							calculatePoints(-10);
						} else {
							calculatePoints(20);
						}
					}
					break;
				case VK_SPACE:
					frog.setDeltaPos(new Vertex(0, 0));
					break;
				}
				menu.setStatus(points, resets, status);
			}
		});

		addTracks();

		setFocusable(true);
		requestFocusInWindow();
	}

	void addTracks() {
		for (int i = 0; i < TRACK_NUMBER; i++)
			addTrains(i);
	}

	void addTrains(int trackNr) {
		double speed = Math.random() * maxSpeed * 2 + minSpeed;
		if (speed > maxSpeed + minSpeed)
			speed = speed - (2 * maxSpeed + minSpeed);

		int filled = 0;
		while (filled < preferredWidth + 300) {

			ImageIcon icon = trainIcons[(int) (Math.random() * trainIcons.length)];
			// final int x = speed < 0 ? filled : -filled;
			final GameObject train = new MovableImage(icon, filled,
					(1 + trackNr) * TRACK_HEIGHT, speed, 0);
			gos.add(train);

			filled = filled + (int) train.getWidth()
					+ ((int) (Math.random() * maxSpace)) + minSpace;
		}

		fillings[trackNr] = filled;
	}

	int[] fillings = new int[TRACK_NUMBER];

	int getFill(double y) {
		return fillings[(int) (y - TRACK_HEIGHT) / TRACK_HEIGHT];
	}

	void resetFrog() {
		frog.getPos().setX(preferredWidth / 2);
		frog.getPos().setY(preferredHeight - TRACK_HEIGHT);
		frog.setDeltaPos(new Vertex(0, 0));
		bonusStageActive = false;		
		status = "";
		
	}

	public void reset() {
		gos = new LinkedList<GameObject>();
		resetFrog();
		addTracks();
		gos.add(frog);
		startTime();
		bonusPoints=1500;
	}

	@Override
	public void doChecks() {

		for (GameObject go : gos)
			if (go != frog) {
				if (!bonusStageActive && this.frog.getPos().getY() == 0) {
					startBonusStage();
				}
				if (bonusStageActive && this.frog.getPos().getY() == 450) {
					win();
				}
				if (frog.getPos().getX() <= 0) {
					frog.getPos().setX(0);
					frog.setDeltaPos(new Vertex(0, 0));
				}
				if (frog.getPos().getX() >= 755) {
					frog.getPos().setX(755);
					frog.setDeltaPos(new Vertex(0, 0));
				}

				if (currentTime < getTime()) {
					currentTime = (System.currentTimeMillis() / 1000)
							- startTime;
					if (!(bonusPoints == 0) && !(1500 - (getTime() * 5) < 0)) {
						bonusPoints = 1500 - (getTime() * 5);
					} else {
						bonusPoints = 0;
					}
					menu.setStatus(points, resets, status);
				}

				if (go.touches(frog)) {
					if (!bonusStageActive)
						calculatePoints(-30);
					resetFrog();
					resets += 1;
					if (!bonusStageActive)
						calculatePoints(-30);
					menu.setStatus(points, resets, status);
				}

				if (go.getDeltaPos().x > 0 && go.getPos().x > preferredWidth)
					go.getPos().addMod(new Vertex(-getFill(go.getPos().y), 0));
				else if (go.getDeltaPos().x < 0
						&& go.getPos().x + go.getWidth() < 0)
					go.getPos().addMod(new Vertex(getFill(go.getPos().y), 0));
			}
	}

	private void win() {
		System.out.println("GEWONNEN");
		status = "GEWONNEN";
	}

	private void startBonusStage() {
		calculatePoints(100);
		bonusStageActive = true;
		status = " !! B O N U S !! ";
		this.setBackground(java.awt.Color.BLUE);
		menu.setStatus(points, resets, status);
	}

	public static void main(String[] args) {
		new ControlledWindow(new TrainFrogger()).setResizable(false);
	}

	public void setMenu(MenuFrogger menuFrogger) {
		this.menu = menuFrogger;
	}

	private void calculatePoints(int points) {
		if (this.points + points > 0) {
			this.points += points;
		} else {
			this.points = 0;
		}
	}

	public void startTime() {
		startTime = System.currentTimeMillis() / 1000;
	}

	public long getTime() {
		return ((System.currentTimeMillis() / 1000) - startTime);
	}

	public long getBonusPoints() {
		return bonusPoints;
	}
}
